package com.polaris.live.widget

import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout

import com.polaris.live.R

/**
 * 适配最大大小的布局
 *
 * @author Created by lucas on 2023/11/7 14:59
 * @since 1.0.0
 */
class AdaptiveLinearLayout(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {

    /**
     * 最小宽度
     */
    var minWidth: Int = 0
        set(value) {
            field = value
            requestLayoutAndInvalidate()
        }

    /**
     * 最大宽度
     */
    var maxWidth: Int = 0
        set(value) {
            field = value
            requestLayoutAndInvalidate()
        }

    /**
     * 最小高度
     */
    var minHeight: Int = 0
        set(value) {
            field = value
            requestLayoutAndInvalidate()
        }

    /**
     * 最大高度
     */
    var maxHeight: Int = 0
        set(value) {
            field = value
            requestLayoutAndInvalidate()
        }

    init {
        if (attrs != null) {
            val styleAttr = context.obtainStyledAttributes(attrs, R.styleable.AdaptiveLinearLayout)
            minWidth = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_min_width, 0F).toInt()
            maxWidth = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_max_width, 0F).toInt()
            minHeight = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_min_height, 0F).toInt()
            maxHeight = styleAttr.getDimension(R.styleable.AdaptiveLinearLayout_max_height, 0F).toInt()
            styleAttr.recycle()
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        //测量最大值
        val widthMS = getMaxMeasureSpec(widthMeasureSpec, maxWidth)
        val heightMS = getMaxMeasureSpec(heightMeasureSpec, maxHeight)
        super.onMeasure(widthMS, heightMS)
        //测量最小值
        val minW = getMinWidthMeasureSpec(widthMS)
        val minH = getMinHeightMeasureSpec(heightMS)
        if (widthMS != minW || heightMS != minH) {
            super.onMeasure(minW, minH)
        }
    }

    /**
     * 得到最大值的MeasureSpec
     * AT_MOST 子布局想要多大就可以多大，但是一般来说不会超过父布局的尺寸；（一般对应的父布局尺寸为 wrap_content，父布局无法确定子布局的尺寸）所以用来设置最大值
     */
    private fun getMaxMeasureSpec(measureSpec: Int, value: Int): Int {
        if (value > 0 && MeasureSpec.getSize(measureSpec) > value) {
            return if (MeasureSpec.getMode(measureSpec) == MeasureSpec.AT_MOST) {
                MeasureSpec.makeMeasureSpec(value, MeasureSpec.AT_MOST)
            } else {
                MeasureSpec.makeMeasureSpec(value, MeasureSpec.EXACTLY)
            }
        }
        return measureSpec
    }

    /**
     * 得到最小宽度MeasureSpec
     */
    private fun getMinWidthMeasureSpec(measureSpec: Int): Int {
        return if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY
            && measuredWidth < minWidth
        ) {
            MeasureSpec.makeMeasureSpec(minWidth, MeasureSpec.EXACTLY)
        } else measureSpec
    }

    /**
     * 得到最小高度MeasureSpec
     */
    private fun getMinHeightMeasureSpec(measureSpec: Int): Int {
        //父布局没有设置EXACTLY，那么此时判断测量后的高度小于最小高度，直接明确设置.如果父布局明确设置为EXACTLY 则直接设置为按照父布局的设置来
        return if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY
            && measuredHeight < minHeight
        ) {
            MeasureSpec.makeMeasureSpec(minHeight, MeasureSpec.EXACTLY)
        } else measureSpec
    }

    /**
     * 布局重新请求绘制
     */
    private fun requestLayoutAndInvalidate() {
        requestLayout()
        invalidate()
    }
}
